home *** CD-ROM | disk | FTP | other *** search
- /*
- * Upside-down DA...a somewhat disappointing experiment
- *
- * Jan Gray 1986
- *
- * link: accstart,ud,aesbind,osbind
- */
-
- #include "gemdefs.h"
- #include "osbind.h"
-
- #define NULL 0
- #define SCR_BYTES 32000L
- #define SCR_ALIGN 512L /* must page align screen */
- #define Supexec(code) xbios(38, code)
-
- typedef unsigned char Byte; /* must be unsigned! */
-
- Byte RevBytes[256];
-
- Byte *RealScreen; /* real screen address */
- Byte *FlipScreen; /* flipped screen address */
- Byte *Phys; /* passed to setPhysBase() */
-
- setPhysBase();
-
- main()
- {
- extern int gl_apid;
- char menuName[20];
- int menuID;
- int event;
- int msg[8];
- int ret;
-
- appl_init();
-
- buildRevBytes();
-
- RealScreen = Physbase();
- FlipScreen = (Byte *)((Malloc(SCR_BYTES + SCR_ALIGN) + (SCR_ALIGN-1))
- & ~(SCR_ALIGN-1));
-
- menuName[0] = NULL;
- menuID = menu_register(gl_apid, menuName);
-
- for (;;) {
- /* Wait for accessory open message */
- strcpy(menuName, " Upside-down");
- do {
- event = evnt_mesag(msg);
- } while (!(msg[0] == AC_OPEN && msg[4] == menuID));
-
- /* Flip screen */
- Phys = FlipScreen;
- Supexec(setPhysBase);
- refreshFlip();
-
- /*
- * Wait for accessory open message or 130 ms timeout.
- * 130 ms should give roughly 50% duty cycle.
- */
- strcpy(menuName, " Rightside-up");
- do {
- event = evnt_multi(MU_MESAG | MU_TIMER,
- 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- msg, 130, 0,
- &ret, &ret, &ret, &ret, &ret, &ret);
- if (event & MU_TIMER)
- refreshFlip();
- } while (!((event & MU_MESAG) &&
- msg[0] == AC_OPEN && msg[4] == menuID));
-
- /* Restore screen */
- Phys = RealScreen;
- Supexec(setPhysBase);
- }
- }
-
- buildRevBytes() /* Build the byte reversal table */
- {
- register int i;
-
- for (i = 0; i < 256; i++)
- RevBytes[i] = ((i & 1) << 7) | ((i & 2) << 5) |
- ((i & 4) << 3) | ((i & 8) << 1) |
- ((i & 0x10) >> 1) | ((i & 0x20) >> 3) |
- ((i & 0x40) >> 5) | ((i & 0x80) >> 7);
- }
-
- #define VBASE_HIGH (Byte *)0xff8201L
- #define VBASE_LOW (Byte *)0xff8203L
- /*
- * setPhysBase -- set the physical screen to Phys. I don't use Setscreen()
- * because it seems to clear the old logical screen...I don't want the
- * ST to know that anything funny is going on, just to go merrily on its
- * way writing to what it thinks is the physical screen...
- */
- setPhysBase()
- {
- *VBASE_HIGH = (Byte)((unsigned long)Phys >> 16);
- *VBASE_LOW = (Byte)((unsigned long)Phys >> 8);
- }
-
- /*
- * Copy the flip of the real screen to FlipScreen. Scans the real screen
- * from last byte to first, writing to the flip screen from first byte
- * to last.
- */
- refreshFlip()
- {
- register /* a5 */ Byte *real = RealScreen + SCR_BYTES;
- register /* a4 */ Byte *flip = FlipScreen;
- register /* a3 */ Byte *rev = RevBytes;
- register int count = SCR_BYTES/8;
-
- /*
- * Copy bytes of the real screen to the flip screen, through
- * the byte reverse table. Unrolled 8 times for speed.
- *
- * Written in assembler (probably not optimal assembler...)
- * because Alcyon C 4.14 generates really really stupid code
- * (like "andi #$ff, d0" followed by "andi.l #$ff, d0"). Oh, God.
- *
- * Expected time: 4 us/byte * 32000 bytes = 130 ms
- */
- while (count-- > 0) {
- #ifdef STUPID_ALCYON_C
- #define COPY *flip++ = rev[*--real];
- #else
- asm("moveq #0,d0"); /* clear upper byte of d0.w */
-
- #define COPY asm("move.b -(a5),d0"); /* 10->12 cycles == 1.5 us */\
- asm("move.b 0(a3,d0.w),(a4)+"); /* 18->20 cycles == 2.5 us */
- #endif
-
- COPY COPY COPY COPY COPY COPY COPY COPY
- }
- }
-
- /* Writing strcpy here saves us from linking with gemlib */
- strcpy(dst, src)
- register char *dst;
- register char *src;
- {
- while (*dst++ = *src++)
- ;
- }
-